<!DOCTYPE html>
<html>
<body>
<script src="../resources/js-test.js"></script>
<script src="../resources/visibility.js"></script>
<script>
description("Tests that gamepad events are not fired when page is hidden but kept as pending and fired when the page becomes visible again.");
window.jsTestIsAsync = true;

var listeners;
function addListener(eventName, handler) {
    if (!listeners)
        listeners = new Array();
    listeners.push({name: eventName, handler: handler});
    window.addEventListener(eventName, handler);
}
function removeListeners() {
    if (!listeners)
        return;
    listeners.forEach(function (l) {
        window.removeEventListener(l.name, l.handler);
    });
}

function finishSoon() {
    setTimeout(finishJSTest, 50);
}

var eventCounter = 0;
var expectations = [
    { index: 0, connected: false, check: null },
    { index: 1, connected: false, check:
        function(event) {
            shouldBeEqualToString('event.gamepad.id', "old");
        }
    },
    { index: 1, connected: true, check:
        function(event) {
            shouldBeEqualToString('event.gamepad.id', "new");
        }
    },
    { index: 2, connected: true, check: null }
];
var expected;

function allTestsCompleted() {
    return eventCounter == expectations.length;
}

function testWithPageVisibleAgain() {
    shouldBeEqualToString('document.visibilityState', 'hidden');
    removeListeners();

    window.addEventListener('gamepadconnected', function(event) {
        shouldBeTrue('eventCounter < expectations.length');
        expected = expectations[eventCounter++];
        shouldBeEqualToNumber('event.gamepad.index', expected.index);
        shouldBeTrue('expected.connected');
        shouldBeTrue('event.gamepad.connected');
        if (expected.check)
            expected.check(event);

        if (allTestsCompleted())
            finishSoon(); // Give some time to fail if unexpecteds events are coming.
    });
    window.addEventListener('gamepaddisconnected', function(event) {
        shouldBeTrue('eventCounter < expectations.length');
        expected = expectations[eventCounter++];
        shouldBeEqualToNumber('event.gamepad.index', expected.index);
        shouldBeFalse('expected.connected');
        shouldBeFalse('event.gamepad.connected');
        if (expected.check)
            expected.check(event);

        if (allTestsCompleted())
            finishSoon(); // Give some time to fail if unexpecteds events are coming.
    });

    setMainWindowHidden(false);
}

function testWithPageHidden() {
    var shouldNotReceive = function() {
        testFailed('Should not have received gamepad events while the page was hidden');
        finishJSTest();
    };
    addListener('gamepadconnected', shouldNotReceive);
    addListener('gamepaddisconnected', shouldNotReceive);

    gamepadController.disconnect(0);

    // Both the disconnection and the connection should be dispatched.
    gamepadController.disconnect(1);
    gamepadController.setId(1, "new");
    gamepadController.connect(1);
    gamepadController.dispatchConnected(1);

    // These should be suppressed.
    gamepadController.connect(2);
    gamepadController.dispatchConnected(2);
    gamepadController.disconnect(2);

    gamepadController.connect(2);
    gamepadController.dispatchConnected(2);

    setTimeout(testWithPageVisibleAgain, 0);
}

if (!window.testRunner || !window.gamepadController) {
    debug("This test cannot work without testRunner and gamepadController.");
}

addListener('gamepadconnected', function() {
    testPassed("Received a gamepadconnected event");
    shouldBeEqualToNumber('event.gamepad.index', 0);
    removeListeners();

    setMainWindowHidden(true).then(testWithPageHidden);
});

gamepadController.connect(0);
gamepadController.dispatchConnected(0);
gamepadController.setId(1, "old");
gamepadController.connect(1);
gamepadController.dispatchConnected(1);

</script>
</html>
